#ifndef JCEREADER_H
#define JCEREADER_H

#include "datareader.h"

class JceReader : public DataReader
{
private:
    enum class ParseMode:qint8{
        QMAPINTVAR, //means a struct
        QMAPVARVAR,//means a map
        QLISTVAR//means a list
    };
public:
    enum class JceDataType:qint8{
        BYTE = 0,
        DOUBLE = 5,
        FLOAT = 4,
        INT = 2,
        LIST = 9,
        LONG = 3,
        MAP = 8,
        SHORT = 1,
        SIMPLE_LIST = 13,
        STRING1 = 6,
        STRING4 = 7,
        STRUCT_BEGIN = 10,
        STRUCT_END = 11,
        ZERO_TYPE = 12
    };
    class HeadData{
    public:
        HeadData() = delete;
        HeadData(JceReader & reader);
        JceDataType type;
        qint8 tag;
    };
public:
    JceReader() = delete;
    JceReader(const QByteArray & data);
    JceReader &setServerEncoding(bool isGBK = true);
    //QVariant parseObj();
    JceReader &parseObj(QVariant & ret);
    QVariantMap parseObj();
    JceReader &setData(const QByteArray & data);
    static QVariantMap &convertQVMap(QVariant & data);
private:
    void retValue(QVariant & ret,int & retTag,QVariant obj,int tag,bool readOnce);
    void parseObj(QVariant & ret,int & retTag,bool readOnce = false);
    /*JceReader &skipToTag(int tag);
    JceReader &readHead(JceDataType type);
    JceReader &readInt(int tag,int &data);
    JceReader &readByte(int tag,qint8 &data);
    JceReader &readShort(int tag,short &data);
    JceReader &readLong(int tag,qint64 &data);
    JceReader &readNull(int tag);
    JceReader &readBytes(int tag,QByteArray &data);
    JceReader &readString(int tag,QString &data);
    JceReader &readFloat(int tag,float &data);
    JceReader &readDouble(int tag,double &data);
    JceReader &readStruct(int tag,JceReader &data);
    JceReader &setData(const QByteArray &data);
    template<typename T>
    JceReader &readList(int tag,QList<T> &data);
    template<typename TKEY,typename TVALUE>
    JceReader &readMap(int tag,QMap<TKEY, TVALUE> &data);

    virtual JceReader &deserialize(){return *this;};
    //the function can be override by subclass
    //then we can use template method to generate it automatically
    //WARN call this twice may cause wrong

    inline JceReader &read(int tag,int &data){return JceReader::readInt(tag,data);}
    inline JceReader &read(int tag,qint8 &data){return JceReader::readByte(tag,data);}
    inline JceReader &read(int tag,short &data){return JceReader::readShort(tag,data);}
    inline JceReader &read(int tag,qint64 &data){return JceReader::readLong(tag,data);}
    //inline JceReader & read(int tag,){return JceReader::readNull(int tag,tag);}
    inline JceReader &read(int tag,QByteArray &data){return JceReader::readBytes(tag,data);}
    inline JceReader &read(int tag,QString &data){return JceReader::readString(tag,data);}
    inline JceReader &read(int tag,float &data){return JceReader::readFloat(tag,data);}
    inline JceReader &read(int tag,double &data){return JceReader::readDouble(tag,data);}
    inline JceReader &read(int tag,JceReader &data){return JceReader::readStruct(tag,data);}
    template<typename TKEY,typename TVALUE>
    inline JceReader &read(int tag,QMap<TKEY, TVALUE> &data){return JceReader::readMap(tag,data);}
    template<typename T>
    inline JceReader &read(int tag,QList<T> &data){return JceReader::readList<T>(tag,data);}
    template<typename T>
    inline JceReader &readT(int tag,T &data){return JceReader::read(tag,data);}*/
private:
    bool sServerEncodingGBK = true;//UTF-8
    static int JCE_MAX_STRING_LENGTH;
};

/*
template<typename T>
JceReader &JceReader::readList(int tag, QList<T> &data)
{

}

template<typename TKEY, typename TVALUE>
JceReader &JceReader::readMap(int tag, QMap<TKEY, TVALUE> &data)
{

}
*/
#endif // JCEREADER_H
